package com.microservice.wechat.scheduler;

import com.microservice.common.util.MailUtil;
import com.microservice.wechat.entity.WechatConfig;
import com.microservice.wechat.mapper.WechatConfigMapper;
import com.microservice.wechat.service.WechatTokenService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 草稿箱数量统计定时任务
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DraftCountScheduler {
    
    private final WechatConfigMapper wechatConfigMapper;
    private final WechatTokenService wechatTokenService;
    private final MailUtil mailUtil;
    private final StringRedisTemplate redisTemplate;
    private final RestTemplate restTemplate = new RestTemplate();
    
    private static final String LOCK_KEY = "draft:count:scheduler:lock";
    private static final String DRAFT_COUNT_URL = "https://api.weixin.qq.com/cgi-bin/draft/count?access_token=";
    
    /**
     * 每天早上8:30、下午2:30、晚上9:30执行
     * cron表达式: 秒 分 时 日 月 周
     */
    @Scheduled(cron = "0 30 8,14,21 * * ?")
    public void syncDraftCount() {
        // 尝试获取分布式锁，防止多实例同时执行
        Boolean lockAcquired = redisTemplate.opsForValue().setIfAbsent(LOCK_KEY, "1", 5, TimeUnit.MINUTES);
        if (lockAcquired == null || !lockAcquired) {
            log.info("未获取到分布式锁，跳过本次草稿箱统计任务");
            return;
        }
        
        try {
            log.info("开始执行草稿箱数量统计任务");
            
            // 获取所有启用的微信配置
            List<WechatConfig> configs = wechatConfigMapper.selectList(null);
            
            if (configs == null || configs.isEmpty()) {
                log.warn("没有找到微信配置");
                return;
            }
            
            // 遍历每个配置
            for (WechatConfig config : configs) {
                if (config.getIsEnabled() == null || config.getIsEnabled() != 1) {
                    log.debug("跳过未启用的配置: {}", config.getAccountName());
                    continue;
                }
                
                try {
                    processDraftCount(config);
                } catch (Exception e) {
                    log.error("处理配置失败: {}, error={}", config.getAccountName(), e.getMessage(), e);
                }
            }
            
            log.info("草稿箱数量统计任务执行完成");
        } finally {
            redisTemplate.delete(LOCK_KEY);
        }
    }
    
    /**
     * 处理单个配置的草稿箱统计
     */
    private void processDraftCount(WechatConfig config) {
        log.info("开始处理配置: {}", config.getAccountName());
        
        // 检查邮箱配置
        if (!StringUtils.hasText(config.getEmail())) {
            log.warn("配置 {} 没有设置邮箱，跳过", config.getAccountName());
            return;
        }
        
        // 使用 WechatTokenService 获取 access_token
        String accessToken = null;
        try {
            accessToken = wechatTokenService.getAccessToken(config.getAppId());
        } catch (Exception e) {
            log.error("获取 access_token 失败: {}, error={}", config.getAccountName(), e.getMessage());
            sendErrorEmail(config.getEmail(), config.getAccountName(), "获取 access_token 失败: " + e.getMessage());
            return;
        }
        
        if (!StringUtils.hasText(accessToken)) {
            log.error("获取 access_token 失败: {}", config.getAccountName());
            sendErrorEmail(config.getEmail(), config.getAccountName(), "获取 access_token 失败");
            return;
        }
        
        // 获取草稿箱数量
        Integer draftCount = getDraftCount(accessToken);
        if (draftCount == null) {
            log.error("获取草稿箱数量失败: {}", config.getAccountName());
            sendErrorEmail(config.getEmail(), config.getAccountName(), "获取草稿箱数量失败");
            return;
        }
        
        // 如果草稿数量为0，则不发送邮件
        if (draftCount == 0) {
            log.info("草稿箱数量为0，不发送邮件: {}", config.getAccountName());
            log.info("处理配置完成: {}, 草稿箱数量: {}", config.getAccountName(), draftCount);
            return;
        }
        
        // 发送邮件通知（仅当草稿数量 > 0 时）
        sendDraftCountEmail(config.getEmail(), config.getAccountName(), draftCount);
        
        log.info("处理配置完成: {}, 草稿箱数量: {}", config.getAccountName(), draftCount);
    }
    
    /**
     * 获取草稿箱数量
     */
    private Integer getDraftCount(String accessToken) {
        try {
            String url = DRAFT_COUNT_URL + accessToken;
            
            // 先获取为 String，避免 Content-Type 为 text/plain 导致的解析问题
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
            
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                String responseBody = response.getBody();
                
                // 打印接口原始返回信息
                log.info("微信草稿箱接口原始返回: {}", responseBody);
                
                // 手动解析 JSON
                Map<String, Object> body = parseJsonToMap(responseBody);
                if (body == null) {
                    log.error("解析微信API返回的JSON失败: {}", responseBody);
                    return null;
                }
                
                // 检查是否有错误码（有些情况会返回错误）
                if (body.containsKey("errcode")) {
                    Object errcodeObj = body.get("errcode");
                    Integer errcode = errcodeObj instanceof Integer ? (Integer) errcodeObj : 
                                     (errcodeObj != null ? Integer.parseInt(errcodeObj.toString()) : null);
                    if (errcode != null && errcode != 0) {
                        log.error("微信API返回错误: errcode={}, errmsg={}", errcode, body.get("errmsg"));
                        return null;
                    }
                }
                
                // 获取草稿箱数量（成功时直接返回 total_count）
                if (body.containsKey("total_count")) {
                    Object totalCount = body.get("total_count");
                    if (totalCount instanceof Integer) {
                        return (Integer) totalCount;
                    } else if (totalCount != null) {
                        // 处理可能是 Long 或 String 的情况
                        return Integer.parseInt(totalCount.toString());
                    }
                }
                
                log.warn("微信API返回数据中没有 total_count 字段: {}", body);
            }
        } catch (Exception e) {
            log.error("请求草稿箱数量异常", e);
        }
        return null;
    }
    
    /**
     * 简单的 JSON 解析为 Map
     */
    private Map<String, Object> parseJsonToMap(String json) {
        try {
            Map<String, Object> map = new HashMap<>();
            // 去除首尾的 { }
            String content = json.trim();
            if (content.startsWith("{") && content.endsWith("}")) {
                content = content.substring(1, content.length() - 1).trim();
            }
            
            // 简单解析 key:value
            String[] pairs = content.split(",");
            for (String pair : pairs) {
                String[] keyValue = pair.split(":");
                if (keyValue.length == 2) {
                    String key = keyValue[0].trim().replace("\"", "");
                    String value = keyValue[1].trim().replace("\"", "");
                    
                    // 尝试转换为数字
                    try {
                        map.put(key, Integer.parseInt(value));
                    } catch (NumberFormatException e) {
                        map.put(key, value);
                    }
                }
            }
            return map;
        } catch (Exception e) {
            log.error("解析JSON失败", e);
            return null;
        }
    }
    
    /**
     * 发送草稿箱数量邮件
     */
    private void sendDraftCountEmail(String email, String accountName, int count) {
        try {
            String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            
            String template = """
                <html>
                <body style="font-family: Arial, sans-serif;">
                    <div style="max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9f9f9;">
                        <h2 style="color: #4CAF50;">📊 小主好！微信公众号草稿箱统计，请及时登录微信公众平台app进行发布草稿！</h2>
                        
                        <div style="background-color: white; padding: 20px; border-radius: 5px; margin: 20px 0;">
                            <p><strong>公众号名称：</strong>${accountName}</p>
                            <p><strong>草稿箱数量：</strong><span style="color: #4CAF50; font-size: 24px; font-weight: bold;">${count}</span> 篇</p>
                            <p><strong>统计时间：</strong>${time}</p>
                        </div>
                        
                        <div style="background-color: #fff3cd; padding: 15px; border-left: 4px solid #ffc107; margin: 20px 0;">
                            <p style="margin: 0; color: #856404;">
                                💡 <strong>提示：</strong>如果草稿箱文章较多，建议及时整理或发布。
                            </p>
                        </div>
                        
                        <hr style="border: none; border-top: 1px solid #ddd; margin: 20px 0;">
                        
                    </div>
                </body>
                </html>
                """;
            
            Map<String, String> params = new HashMap<>();
            params.put("accountName", accountName);
            params.put("count", String.valueOf(count));
            params.put("time", currentTime);
            
            // 异步发送邮件
            mailUtil.sendTemplateMailAsync(
                email,
                "【微信公众号】草稿箱统计报告 - " + accountName,
                template,
                params
            );
            
            log.info("草稿箱统计邮件已发送到: {}", email);
        } catch (Exception e) {
            log.error("发送草稿箱统计邮件失败: email={}", email, e);
        }
    }
    
    /**
     * 发送错误邮件
     */
    private void sendErrorEmail(String email, String accountName, String errorMsg) {
        try {
            String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            
            String template = """
                <html>
                <body style="font-family: Arial, sans-serif;">
                    <div style="max-width: 600px; margin: 0 auto; padding: 20px; background-color: #f9f9f9;">
                        <h2 style="color: #f44336;">⚠️ 草稿箱统计失败</h2>
                        
                        <div style="background-color: white; padding: 20px; border-radius: 5px; margin: 20px 0;">
                            <p><strong>公众号名称：</strong>${accountName}</p>
                            <p><strong>错误信息：</strong><span style="color: #f44336;">${errorMsg}</span></p>
                            <p><strong>发生时间：</strong>${time}</p>
                        </div>
                        
                        <div style="background-color: #f8d7da; padding: 15px; border-left: 4px solid #f44336; margin: 20px 0;">
                            <p style="margin: 0; color: #721c24;">
                                请检查：<br>
                                1. AppID 和 AppSecret 是否正确<br>
                                2. 公众号是否有草稿箱权限<br>
                                3. access_token 是否正常获取
                            </p>
                        </div>
                        
                        <hr style="border: none; border-top: 1px solid #ddd; margin: 20px 0;">
                        
                        <p style="color: #999; font-size: 12px;">
                            这是一封自动发送的错误通知邮件。<br>
                            如需帮助，请联系系统管理员。
                        </p>
                    </div>
                </body>
                </html>
                """;
            
            Map<String, String> params = new HashMap<>();
            params.put("accountName", accountName);
            params.put("errorMsg", errorMsg);
            params.put("time", currentTime);
            
            // 异步发送邮件
            mailUtil.sendTemplateMailAsync(
                email,
                "【微信公众号】草稿箱统计失败 - " + accountName,
                template,
                params
            );
            
            log.info("错误通知邮件已发送到: {}", email);
        } catch (Exception e) {
            log.error("发送错误通知邮件失败: email={}", email, e);
        }
    }
    
    /**
     * 手动触发统计（用于测试）
     */
    public void manualSync() {
        log.info("手动触发草稿箱统计任务");
        syncDraftCount();
    }
}
